package com.mars.module.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.mars.common.response.PageInfo;
import com.mars.common.request.sys.SysRoleQueryRequest;
import com.mars.common.request.sys.SysRoleAddRequest;
import com.mars.common.request.sys.SysRoleUpdateRequest;
import com.mars.common.response.sys.SysRoleDetailResponse;
import com.mars.common.response.sys.SysRoleListResponse;
import com.mars.common.util.StringUtil;
import com.mars.framework.exception.ServiceException;
import com.mars.module.system.entity.SysUserRole;
import com.mars.module.system.mapper.SysRoleMapper;
import com.mars.module.system.mapper.SysRoleMenuMapper;
import com.mars.module.system.entity.SysRole;
import com.mars.module.system.entity.SysRoleMenu;
import com.mars.common.util.IdUtils;
import com.mars.module.system.mapper.SysUserRoleMapper;
import com.mars.module.system.service.ISysRoleService;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 角色Service
 *
 * @author 源码字节-程序员Mars
 */
@Service
@AllArgsConstructor
public class SysRoleServiceImpl implements ISysRoleService {

    private final SysRoleMapper sysRoleMapper;

    private final SysUserRoleMapper sysUserRoleMapper;

    private final SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    public List<SysRoleListResponse> selectAll() {
        List<SysRole> list = sysRoleMapper.selectList(null);
        List<SysRoleListResponse> roleVoList = new ArrayList<>();
        for (SysRole sysRole : list) {
            SysRoleListResponse roleVo = new SysRoleListResponse();
            BeanUtils.copyProperties(sysRole, roleVo);
            roleVoList.add(roleVo);
        }
        return roleVoList;
    }

    @Override
    public PageInfo<SysRoleListResponse> list(SysRoleQueryRequest request) {
        LambdaQueryWrapper<SysRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtil.isNotEmpty(request.getRoleName()), SysRole::getRoleName, request.getRoleName());
        IPage<SysRoleListResponse> page = sysRoleMapper.selectPage(request.page(), wrapper).convert(x -> {
            SysRoleListResponse vo = new SysRoleListResponse();
            BeanUtils.copyProperties(x, vo);
            return vo;
        });
        return PageInfo.build(page);
    }

    @Override
    public SysRoleDetailResponse get(Long id) {
        SysRole sysRole = sysRoleMapper.selectById(id);
        if (sysRole == null) {
            throw new ServiceException("数据不存在");
        }
        SysRoleDetailResponse sysRoleDetailResponse = new SysRoleDetailResponse();
        BeanUtils.copyProperties(sysRole, sysRoleDetailResponse);
        sysRoleDetailResponse.setMenuId(sysRoleMenuMapper.selectByRoleId(id));
        return sysRoleDetailResponse;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysRoleAddRequest addDto) {
        SysRole role = sysRoleMapper.selectOne(Wrappers.lambdaQuery(SysRole.class).eq(SysRole::getRoleName, addDto.getRoleName()));
        if (Objects.nonNull(role)) {
            throw new ServiceException("当前角色已添加");
        }
        //新增角色
        SysRole sysRole = new SysRole();
        sysRole.setId(IdUtils.getLongId());
        sysRole.setRoleName(addDto.getRoleName());
        sysRole.setRemark(addDto.getRemark());
        sysRole.setCreateTime(LocalDateTime.now());
        sysRole.setUpdateTime(sysRole.getCreateTime());
        sysRoleMapper.insert(sysRole);

        //新增角色权限
        List<Long> menuList = addDto.getMenuId();
        if (menuList != null && menuList.size() > 0) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(sysRole.getId());
            for (Long menuId : menuList) {
                sysRoleMenu.setId(IdUtils.getLongId());
                sysRoleMenu.setMenuId(menuId);
                sysRoleMenu.setCreateTime(LocalDateTime.now());
                sysRoleMenu.setUpdateTime(sysRoleMenu.getCreateTime());
                sysRoleMenuMapper.insert(sysRoleMenu);
            }
        }
    }

    @Override
    public void delete(Long id) {
        // 查询该角色是否绑定用户
        Long count = sysUserRoleMapper.selectCount(Wrappers.lambdaQuery(SysUserRole.class)
                .eq(SysUserRole::getRoleId, id));
        if (count > 0) {
            throw new ServiceException("当前角色已绑定用户，无法删除");
        }
        //删除角色菜单
        sysRoleMenuMapper.deleteByRoleId(id);
        //删除角色
        sysRoleMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(SysRoleUpdateRequest request) {
        SysRole sysRole = sysRoleMapper.selectById(request.getId());
        if (Objects.isNull(sysRole)) {
            throw new ServiceException("数据不存在");
        }
        //修改角色
        sysRole.setRoleName(request.getRoleName());
        sysRole.setRemark(request.getRemark());
        sysRoleMapper.updateById(sysRole);
        //删除原有角色菜单
        sysRoleMenuMapper.deleteByRoleId(request.getId());
        //新增新的角色菜单
        if (CollectionUtils.isNotEmpty(request.getMenuId())) {
            List<SysRoleMenu> menuList = request.getMenuId().stream().map(x -> {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(request.getId());
                sysRoleMenu.setId(IdUtils.getLongId());
                sysRoleMenu.setMenuId(x);
                sysRoleMenu.setCreateTime(LocalDateTime.now());
                sysRoleMenu.setUpdateTime(sysRoleMenu.getCreateTime());
                return sysRoleMenu;
            }).collect(Collectors.toList());
            sysRoleMenuMapper.insertBatchSomeColumn(menuList);
        }
    }
}
